package client;
import java.awt.*;
import java.awt.image.BufferedImage;

import javax.swing.*;

import util.GameConstants;
import util.UIConstants;


public class GameView extends JPanel{
	private static final long serialVersionUID = 1L;
	ClientModel client;
	GameModel model;
	private final int playerID;
	GameView window;
	long turnStartTime;
	/** Allows painting to happen. */
	private boolean repaintFlag;
	private boolean painting;
	int xSize, ySize;
	/** How much percent of the turn has gone by already, on a scale from 0-1. */
	double turnPercent;
	
	public GameView(ClientModel tclient) {
		this.window = this;
		this.client = tclient;
		this.model = client.game;
		this.playerID = tclient.playerID;
		this.setFocusable(true);
		this.setDoubleBuffered(true); //not sure if we want this or not.. just gotta experiment
		this.turnStartTime = System.currentTimeMillis();
		this.repaintFlag = true; 
		this.painting = false;
		this.xSize = UIConstants.screenSize+UIConstants.panelBorderWidth+UIConstants.rightPanelWidth;
		this.ySize = UIConstants.screenSize+UIConstants.panelBorderWidth+UIConstants.bottomPanelHeight;
	}
	
	public Dimension getPreferredSize() {
		return new Dimension(xSize, ySize);
	}
	
	public void endTurn(long time) {
		turnStartTime = time;
		repaint();
	}
	
	public boolean isPainting() {
		return painting;
	}
	public void setRepaintFlag (boolean b) {
		repaintFlag = b;
	}
	public int xcoordToPixel(double xcoord) {
		double xPos = model.players[playerID].xLoc+model.players[playerID].xVel*(turnPercent-1);
		return (int)((xcoord-xPos)*UIConstants.pixelsPerCoord+UIConstants.screenSize/2);
	}
	public int ycoordToPixel(double ycoord) {
		double yPos = model.players[playerID].yLoc+model.players[playerID].yVel*(turnPercent-1);
		return (int)((ycoord-yPos)*UIConstants.pixelsPerCoord+UIConstants.screenSize/2);
	}
	public double xpixelToCoord(int pixel) {
		double xPos = model.players[playerID].xLoc+model.players[playerID].xVel*(turnPercent-1);
		return (pixel-+UIConstants.screenSize/2)/UIConstants.pixelsPerCoord+xPos;
	}
	public double ypixelToCoord(int pixel) {
		double yPos = model.players[playerID].yLoc+model.players[playerID].yVel*(turnPercent-1);
		return (pixel-+UIConstants.screenSize/2)/UIConstants.pixelsPerCoord+yPos;
	}

	public void paintComponent(Graphics gg) {
		if(!repaintFlag) return;
		painting = true;
		turnPercent = ((double)System.currentTimeMillis()-turnStartTime)/GameConstants.turnMillis; 
		turnPercent = Math.max(Math.min(turnPercent, 1), 0);
		
		//drawBackground
		gg.setColor(new Color(70,70,70));
		gg.fillRect(0, 0, xSize, ySize);
		
		
		//buffer main panel
		BufferedImage buffer;
		Graphics2D g;
		buffer = new BufferedImage(UIConstants.screenSize, UIConstants.screenSize, BufferedImage.TYPE_INT_RGB);
		g = (Graphics2D)buffer.getGraphics();
		g.setFont(UIConstants.defaultFont);
		paintMainPanel(g);
		gg.drawImage(buffer, 0, 0, UIConstants.screenSize, UIConstants.screenSize, null);
		
		//buffer side panel
		buffer = new BufferedImage(UIConstants.rightPanelWidth, UIConstants.screenSize, BufferedImage.TYPE_INT_RGB);
		g = (Graphics2D)buffer.getGraphics();
		g.setFont(UIConstants.defaultFont);
		paintRightPanel(g);
		gg.drawImage(buffer, UIConstants.screenSize+UIConstants.panelBorderWidth, 0, UIConstants.rightPanelWidth, UIConstants.screenSize, null);
		
		//buffer bottom panel
		buffer = new BufferedImage(xSize, UIConstants.bottomPanelHeight, BufferedImage.TYPE_INT_RGB);
		g = (Graphics2D)buffer.getGraphics();
		g.setFont(UIConstants.defaultFont);
		paintBottomPanel(g);
		gg.drawImage(buffer, 0, UIConstants.screenSize+UIConstants.panelBorderWidth, xSize, UIConstants.bottomPanelHeight, null);
		
		//unlock the paint lock
		painting = false;
	}
	
	public void paintMainPanel(Graphics2D g) {
		//draw terrain
		int xMinCoordOnScreen = Math.max(0, (int)xpixelToCoord(0)-1);
		int xMaxCoordOnScreen = Math.min(model.gameMap.getXmax(), (int)xpixelToCoord(UIConstants.screenSize)+2);
		int yMinCoordOnScreen = Math.max(0, (int)ypixelToCoord(0)-1);
		int yMaxCoordOnScreen = Math.min(model.gameMap.getYmax(), (int)ypixelToCoord(UIConstants.screenSize)+2);
		for(int x=xMinCoordOnScreen; x<xMaxCoordOnScreen; x++) 
			for(int y=yMinCoordOnScreen; y<yMaxCoordOnScreen; y++) {
				TerrainType tt = model.gameMap.getTerrain(x, y);
				Color tileColor = null;
				if(tt==TerrainType.LAND) tileColor = new Color(200, 200, 200);
				else if(tt==TerrainType.WATER) tileColor = new Color(100,100,255);
				else if(tt==TerrainType.WALL) tileColor = new Color(0,20,0);
				g.setColor(tileColor);
				int w = (int)UIConstants.pixelsPerCoord;
				g.fillRect(xcoordToPixel(x), ycoordToPixel(y), w, w);
			}
		
		//draw summons 
		for(Summon su: model.summons) {
			int x = xcoordToPixel(su.xPos);
			int y = ycoordToPixel(su.yPos);
			int r = UIConstants.summonRadius;
			g.setColor(Color.magenta);
			g.drawRect(x-r, y-r, 2*r, 2*r);
			g.setColor(Color.red);
			g.drawRect(x-r+2, y-r+2, 2*r-4, 2*r-4);
		}
		
		//draw players
		for(int p=0; p<model.players.length; p++) {
			g.setColor(p==0?Color.blue:Color.yellow);
			int xPos = xcoordToPixel(model.players[p].xLoc+model.players[p].xVel*(turnPercent-1));
			int yPos = ycoordToPixel(model.players[p].yLoc+model.players[p].yVel*(turnPercent-1));
			if(p==playerID) {
				Point mouseLocation = MouseInfo.getPointerInfo().getLocation();
				double xMouseLocation = mouseLocation.x-this.getLocationOnScreen().x;
				double yMouseLocation = mouseLocation.y-this.getLocationOnScreen().y;
				double dx = xMouseLocation-xPos;
				double dy = yMouseLocation-yPos;
				double dist = Math.sqrt(dx*dx+dy*dy);
				int l = UIConstants.playerScopeLength;
				dx*=l/dist;
				dy*=l/dist;
				g.drawLine(xPos, yPos, xPos+(int)dx, yPos+(int)dy);
			}
			int r = UIConstants.playerRadius;
			g.fillOval(xPos-r, yPos-r, 2*r, 2*r);
			g.setColor(Color.orange);
			g.drawString(""+p, xPos-3, yPos+4);
		}	
		
		//draw spell effects
		for(SpellEffect se: model.spellEffects) {
			if(se.spellType==2) {
				if(se.playerID==playerID) {
					g.setColor(Color.yellow);
					int x = xcoordToPixel(se.xTarget);
					int y = ycoordToPixel(se.yTarget);
					int r = (int)(UIConstants.pixelsPerCoord/2);
					g.drawLine(x-r, y-r, x+r, y+r);
					g.drawLine(x-r, y+r, x+r, y-r);
				}
			} else if(se.spellType==3) {
				g.setColor(Color.red);
				int w = (int)(GameConstants.conflagurationRadius*UIConstants.pixelsPerCoord);
				g.drawOval(xcoordToPixel(se.xTarget)-w, ycoordToPixel(se.yTarget)-w, 2*w, 2*w);
			}
		}
		
		//draw projectiles
		for(Projectile p: model.projectiles.values()) {
			double x = p.xPos+p.xVel*(turnPercent-1);
			double y = p.yPos+p.yVel*(turnPercent-1);
			int r = UIConstants.fireballRadius;
			g.setColor(p.type==1?Color.WHITE:Color.red);
			g.fillOval(xcoordToPixel(x)-r, ycoordToPixel(y)-r, 2*r, 2*r);
		}
		
		//draw collisions
		for(Collision col: model.collisions) {
			double x = col.x;
			double y = col.y;
			int r = (int)(UIConstants.pixelsPerCoord*((col.x==0)?GameConstants.fireballSize:GameConstants.smiteRadius));
			g.setColor((col.type==0)?Color.orange:Color.yellow);
			g.fillOval(xcoordToPixel(x)-r, ycoordToPixel(y)-r, 2*r, 2*r);
		}
	}
	public void paintRightPanel(Graphics2D g) {
		//draw mana sidebars
		int h, hmax=UIConstants.screenSize;
		g.setColor(Color.RED);
		h = (int)(model.players[playerID].fire/GameConstants.maxMana*hmax);
		g.fillRect(0, hmax-h, 20, h);
		g.setColor(Color.WHITE);
		h = (int)(model.players[playerID].light/GameConstants.maxMana*hmax);
		g.fillRect(20, hmax-h, 20, h);
		g.setColor(Color.BLUE);
		h = (int)(model.players[playerID].ice/GameConstants.maxMana*hmax);
		g.fillRect(40, hmax-h, 20, h);
	}
	public void paintBottomPanel(Graphics2D g) {
		g.setColor(new Color(150, 150, 150));
		g.fillRect(0, 0, xSize, UIConstants.bottomPanelHeight);
		g.setColor(Color.black);
		g.drawString("WASD - move", 50, 20);
		g.drawString("space - fireball", 50, 50);
		g.drawString("R - teleport", 250, 20);
		g.drawString("F - sentinel", 250, 50);
		g.drawString("T - smite", 410, 20);
		g.drawString("G - haste", 410, 50);
		g.drawString("Y - scorch", 570, 20);
		g.drawString("H - magic bolt", 570, 50);
	}
}
